<!DOCTYPE html>
    <html>
    <head>
        <meta http-equiv="Content-type" content="text/html;charset=UTF-8">
        <title></title>
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.10.0/dist/katex.min.css" integrity="sha384-9eLZqc9ds8eNjO3TmqPeYcDj8n+Qfa4nuSiGYa6DjLNcv9BtN69ZIulL9+8CqC9Y" crossorigin="anonymous">
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Microsoft/vscode/extensions/markdown-language-features/media/markdown.css">
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Microsoft/vscode/extensions/markdown-language-features/media/highlight.css">
        <link href="https://cdn.jsdelivr.net/npm/katex-copytex@latest/dist/katex-copytex.min.css" rel="stylesheet" type="text/css">
        <style>
.task-list-item { list-style-type: none; } .task-list-item-checkbox { margin-left: -20px; vertical-align: middle; }
</style>
        <style>
            body {
                font-family: -apple-system, BlinkMacSystemFont, 'Segoe WPC', 'Segoe UI', 'HelveticaNeue-Light', 'Ubuntu', 'Droid Sans', sans-serif;
                font-size: 14px;
                line-height: 1.6;
            }
        </style>
        
        <script src="https://cdn.jsdelivr.net/npm/katex-copytex@latest/dist/katex-copytex.min.js"></script>
    </head>
    <body>
        <p>ctaTemplate类所在路径vnpy/trader/app/ctaStrategy/ctaTemplate.py</p>
<pre><code class="language-python"><div><span class="hljs-string">'''
本文件包含了CTA引擎中的策略开发用模板，开发策略时需要继承CtaTemplate类。
'''</span>

<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span>  pd
<span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime,timedelta,time
<span class="hljs-keyword">import</span> talib
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> defaultdict
<span class="hljs-keyword">from</span> vnpy.trader.vtConstant <span class="hljs-keyword">import</span> *
<span class="hljs-keyword">from</span> vnpy.trader.vtObject <span class="hljs-keyword">import</span> VtBarData
<span class="hljs-keyword">from</span> vnpy.trader.vtUtility <span class="hljs-keyword">import</span> BarGenerator, ArrayManager
<span class="hljs-keyword">from</span> vnpy.trader.utils.email <span class="hljs-keyword">import</span> mail

<span class="hljs-keyword">from</span> .ctaBase <span class="hljs-keyword">import</span> *

<span class="hljs-comment">########################################################################</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CtaTemplate</span><span class="hljs-params">(object)</span>:</span>
    <span class="hljs-string">"""CTA策略模板"""</span>

    <span class="hljs-comment"># 策略类的名称和作者</span>
    className = <span class="hljs-string">'CtaTemplate'</span>
    author = EMPTY_UNICODE

    <span class="hljs-comment"># MongoDB数据库的名称，K线数据库默认为1分钟</span>
    tickDbName = TICK_DB_NAME
    barDbName = MINUTE_DB_NAME

    <span class="hljs-comment"># 策略的基本参数</span>
    name = EMPTY_UNICODE  <span class="hljs-comment"># 策略实例名称</span>
    vtSymbol = EMPTY_STRING        <span class="hljs-comment"># 交易的合约vt系统代码</span>
    productClass = EMPTY_STRING  <span class="hljs-comment"># 产品类型（只有IB接口需要）</span>
    currency = EMPTY_STRING  <span class="hljs-comment"># 货币（只有IB接口需要）</span>

    <span class="hljs-comment"># 策略的基本变量，由引擎管理</span>
    inited = <span class="hljs-keyword">False</span>  <span class="hljs-comment"># 是否进行了初始化</span>
    trading = <span class="hljs-keyword">False</span>  <span class="hljs-comment"># 是否启动交易，由引擎管理</span>
    symbolList = []  <span class="hljs-comment"># 策略的标的列表</span>

    <span class="hljs-comment"># 参数列表，保存了参数的名称,列表里的内容最后会显示在qt界面上</span>
    paramList = [<span class="hljs-string">'name'</span>,
                 <span class="hljs-string">'className'</span>,
                 <span class="hljs-string">'author'</span>,
                 <span class="hljs-string">'symbolList'</span>]

    <span class="hljs-comment"># 变量列表，保存了变量的名称，列表里的内容最后会显示在qt界面上</span>
    varList = [<span class="hljs-string">'inited'</span>,
               <span class="hljs-string">'trading'</span>,
               <span class="hljs-string">'posDict'</span>]

    <span class="hljs-comment"># 同步列表，保存了需要保存到数据库的变量名称</span>
    syncList = [<span class="hljs-string">'posDict'</span>,
                <span class="hljs-string">'eveningDict'</span>,
                <span class="hljs-string">'accountDict'</span>]

    <span class="hljs-comment"># ----------------------------------------------------------------------</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, ctaEngine, setting)</span>:</span>
        <span class="hljs-string">"""Constructor"""</span>
        self.ctaEngine = ctaEngine <span class="hljs-comment">#</span>
        self.posDict = {}<span class="hljs-comment">#仓位字典，形式如同{"eosusd_long":1,"eosusd_short":1}表明多空都有，自动在引擎内部生成</span>
        self.eveningDict = {}<span class="hljs-comment">#保证金字典，一般不用</span>
        self.accountDict = {}<span class="hljs-comment">#账户字典，暂时没用上还不知道干啥的</span>
        <span class="hljs-comment"># 设置策略的参数</span>
</div></code></pre>
<p>通过setting里的key和value自动在类内部创建属性，通过往self.__dict__[key]=value的方式
不懂的话可以自行百度self.__dict__</p>
<pre><code class="language-python"><div>        <span class="hljs-keyword">if</span> setting:
            d = self.__dict__
            <span class="hljs-keyword">for</span> key <span class="hljs-keyword">in</span> self.paramList:
                <span class="hljs-keyword">if</span> key <span class="hljs-keyword">in</span> setting:
                    d[key] = setting[key]
        
        <span class="hljs-comment"># self.posDict = {}</span>
        <span class="hljs-comment"># self.eveningDict = {}</span>
        
</div></code></pre>
<p>NotImplementedError可以实现c++的pure virtual的功能，就是说子类必须继承父类的方法并加以实现，否则就报错
引擎上会有四个功能键
初始化-&gt;onInit
启动-&gt;onStart
停止-&gt;onStop
恢复-&gt;onRestore</p>
<pre><code class="language-python"><div>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">onInit</span><span class="hljs-params">(self)</span>:</span>
        <span class="hljs-string">"""初始化策略（必须由用户继承实现）"""</span>
        <span class="hljs-keyword">raise</span> NotImplementedError

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">onStart</span><span class="hljs-params">(self)</span>:</span>
        <span class="hljs-string">"""启动策略（必须由用户继承实现）"""</span>
        <span class="hljs-keyword">raise</span> NotImplementedError

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">onStop</span><span class="hljs-params">(self)</span>:</span>
        <span class="hljs-string">"""停止策略（必须由用户继承实现）"""</span>
        <span class="hljs-keyword">raise</span> NotImplementedError

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">onRestore</span><span class="hljs-params">(self)</span>:</span>
        <span class="hljs-string">"""恢复策略（必须由用户继承实现）"""</span>
        <span class="hljs-keyword">raise</span> NotImplementedError
</div></code></pre>
<p>程序通过websocket与交易所建立持久化连接，交易所会推送给tick数据
引擎内部会把tick数据处理成固定的数据格式
tick的数据格式如下</p>
<pre><code class="language-python"><div>    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">VtTickData</span><span class="hljs-params">(VtBaseData)</span>:</span>
    <span class="hljs-string">"""Tick行情数据类"""</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self)</span>:</span>
        <span class="hljs-string">"""Constructor"""</span>
        super(VtTickData, self).__init__()
        
        <span class="hljs-comment"># 代码相关</span>
        self.symbol = EMPTY_STRING              <span class="hljs-comment"># 合约代码</span>
        self.exchange = EMPTY_STRING            <span class="hljs-comment"># 交易所代码</span>
        self.vtSymbol = EMPTY_STRING            <span class="hljs-comment"># 合约在vt系统中的唯一代码，通常是 合约代码.交易所代码</span>
        
        <span class="hljs-comment"># 成交数据</span>
        self.lastPrice = EMPTY_FLOAT            <span class="hljs-comment"># 最新成交价</span>
        self.lastVolume = EMPTY_INT             <span class="hljs-comment"># 最新成交量</span>
        self.volume = EMPTY_INT                 <span class="hljs-comment"># 今天总成交量</span>
        self.openInterest = EMPTY_INT           <span class="hljs-comment"># 持仓量</span>
        self.time = EMPTY_STRING                <span class="hljs-comment"># 时间 11:20:56.5</span>
        self.date = EMPTY_STRING                <span class="hljs-comment"># 日期 20151009</span>
        self.datetime = <span class="hljs-keyword">None</span>                    <span class="hljs-comment"># python的datetime时间对象</span>
        
        <span class="hljs-comment"># 常规行情</span>
        self.openPrice = EMPTY_FLOAT            <span class="hljs-comment"># 今日开盘价</span>
        self.highPrice = EMPTY_FLOAT            <span class="hljs-comment"># 今日最高价</span>
        self.lowPrice = EMPTY_FLOAT             <span class="hljs-comment"># 今日最低价</span>
        self.preClosePrice = EMPTY_FLOAT
        
        self.upperLimit = EMPTY_FLOAT           <span class="hljs-comment"># 涨停价</span>
        self.lowerLimit = EMPTY_FLOAT           <span class="hljs-comment"># 跌停价</span>
        
        <span class="hljs-comment"># 五档行情</span>
        self.bidPrice1 = EMPTY_FLOAT
        self.bidPrice2 = EMPTY_FLOAT
        self.bidPrice3 = EMPTY_FLOAT
        self.bidPrice4 = EMPTY_FLOAT
        self.bidPrice5 = EMPTY_FLOAT
        self.askPrice1 = EMPTY_FLOAT
        self.askPrice2 = EMPTY_FLOAT
        self.askPrice3 = EMPTY_FLOAT
        self.askPrice4 = EMPTY_FLOAT
        self.askPrice5 = EMPTY_FLOAT        
        self.bidVolume1 = EMPTY_INT
        self.bidVolume2 = EMPTY_INT
        self.bidVolume3 = EMPTY_INT
        self.bidVolume4 = EMPTY_INT
        self.bidVolume5 = EMPTY_INT
        self.askVolume1 = EMPTY_INT
        self.askVolume2 = EMPTY_INT
        self.askVolume3 = EMPTY_INT
        self.askVolume4 = EMPTY_INT
        self.askVolume5 = EMPTY_INT
</div></code></pre>
<p>会把tick传入如下函数，在策略里继承实现</p>
<pre><code class="language-python"><div>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">onTick</span><span class="hljs-params">(self, tick)</span>:</span>
        <span class="hljs-string">"""收到行情TICK推送（必须由用户继承实现）"""</span>
        <span class="hljs-keyword">raise</span> NotImplementedError
</div></code></pre>
<p>onOrder会在订单发生变化的时候，进行推送，通过websocket传来
websocket会订阅很多频道，订单这个单独有一个频道
行情数据也有单独的频道，传来的是json格式，内部处理成order的数据格式，
格式如下</p>
<pre><code class="language-python"><div>    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">VtOrderData</span><span class="hljs-params">(VtBaseData)</span>:</span>
    <span class="hljs-string">"""订单数据类"""</span>

    <span class="hljs-comment">#----------------------------------------------------------------------</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self)</span>:</span>
        <span class="hljs-string">"""Constructor"""</span>
        super(VtOrderData, self).__init__()
        
        <span class="hljs-comment"># 代码编号相关</span>
        self.symbol = EMPTY_STRING              <span class="hljs-comment"># 合约代码</span>
        self.exchange = EMPTY_STRING            <span class="hljs-comment"># 交易所代码</span>
        self.vtSymbol = EMPTY_STRING  <span class="hljs-comment"># 索引，统一格式：f"{symbol}.{exchange}"</span>
        
        self.orderID = EMPTY_STRING             <span class="hljs-comment"># 订单编号 gateway内部自己生成的编号</span>
        self.vtOrderID = EMPTY_STRING  <span class="hljs-comment"># 索引，统一格式：f"{gatewayName}.{orderId}"</span>
        
        <span class="hljs-comment"># 报单相关</span>
        self.direction = EMPTY_UNICODE          <span class="hljs-comment"># 报单方向</span>
        self.offset = EMPTY_UNICODE             <span class="hljs-comment"># 报单开平仓</span>
        self.price = EMPTY_FLOAT                <span class="hljs-comment"># 报单价格</span>
        self.totalVolume = EMPTY_INT            <span class="hljs-comment"># 报单总数量</span>
        self.tradedVolume = EMPTY_INT           <span class="hljs-comment"># 报单成交数量</span>
        self.status = EMPTY_UNICODE             <span class="hljs-comment"># 报单状态</span>
        
        self.orderTime = EMPTY_STRING           <span class="hljs-comment"># 发单时间</span>
        self.cancelTime = EMPTY_STRING          <span class="hljs-comment"># 撤单时间</span>
        
        <span class="hljs-comment"># CTP/LTS相关</span>
        self.frontID = EMPTY_INT                <span class="hljs-comment"># 前置机编号</span>
        self.sessionID = EMPTY_INT 
</div></code></pre>
<p>交易所会发来一个orderID作为唯一标志，传递某一个订单的状态order.status
有“未成交”，“部分成交”，“全部成交”，“已撤销”，“未知”（未知是引擎内部处理的，用于应付掉线情况）
vtOrderID是引擎内部根据orderID维护的一个列表，也是唯一的，按从1开始的顺序递增，方便处理，
所以一般在策略里都使用order.vtOrderID
order.vtSymbol是你交易的品种
order.direction是你下的这单的方向,多或空
order.offset是你下的这单是开仓还是平仓
buy-&gt;“多” “开仓”
sell-&gt;“空” “平仓”
short-&gt;“空” “开仓”
cover-&gt;“多” “平仓”
order.price报单价格
order.totalVolume报单总数量
order.tradedVolume成交数量</p>
<pre><code class="language-python"><div>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">onOrder</span><span class="hljs-params">(self, order)</span>:</span>
        <span class="hljs-string">"""收到委托变化推送（必须由用户继承实现）"""</span>
        <span class="hljs-keyword">raise</span> NotImplementedError
</div></code></pre>
<p>如果是完全成交或部分成交的order.status会被推到onTrade里，顺序在onOrder之后，
所以如果要在onTrade里写东西，最好不要写交易逻辑，不然会要先运行完onOrder再过来，速度跟不上
或者onOrder自己实现异步的，不阻塞到onTrade。
trade的数据格式如下</p>
<pre><code class="language-python"><div>    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">VtTradeData</span><span class="hljs-params">(VtBaseData)</span>:</span>
    <span class="hljs-string">"""
    成交数据类
    一般来说，一个VtOrderData可能对应多个VtTradeData：一个订单可能多次部分成交
    """</span>

    <span class="hljs-comment">#----------------------------------------------------------------------</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self)</span>:</span>
        <span class="hljs-string">"""Constructor"""</span>
        super(VtTradeData, self).__init__()
        
        <span class="hljs-comment"># 代码编号相关</span>
        self.symbol = EMPTY_STRING              <span class="hljs-comment"># 合约代码</span>
        self.exchange = EMPTY_STRING            <span class="hljs-comment"># 交易所代码</span>
        self.vtSymbol = EMPTY_STRING            <span class="hljs-comment"># 合约在vt系统中的唯一代码，通常是 合约代码.交易所代码</span>

        self.tradeID = EMPTY_STRING  <span class="hljs-comment"># 成交编号 gateway内部自己生成的编号</span>
        self.vtTradeID = EMPTY_STRING           <span class="hljs-comment"># 成交在vt系统中的唯一编号，通常是 Gateway名.成交编号</span>
        
        self.orderID = EMPTY_STRING             <span class="hljs-comment"># 订单编号</span>
        self.vtOrderID = EMPTY_STRING           <span class="hljs-comment"># 订单在vt系统中的唯一编号，通常是 Gateway名.订单编号</span>
        
        <span class="hljs-comment"># 成交相关</span>
        self.direction = EMPTY_UNICODE          <span class="hljs-comment"># 成交方向</span>
        self.offset = EMPTY_UNICODE             <span class="hljs-comment"># 成交开平仓</span>
        self.price = EMPTY_FLOAT                <span class="hljs-comment"># 成交价格</span>
        self.volume = EMPTY_INT                 <span class="hljs-comment"># 成交数量</span>
        self.tradeTime = EMPTY_STRING           <span class="hljs-comment"># 成交时间</span>
</div></code></pre>
<p>部分成交和全部成交会被推送到onTrade函数里</p>
<pre><code class="language-python"><div>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">onTrade</span><span class="hljs-params">(self, trade)</span>:</span>
        <span class="hljs-string">"""收到成交推送（必须由用户继承实现）"""</span>
        <span class="hljs-keyword">raise</span> NotImplementedError
</div></code></pre>
<p>bar就是传统的k线，数据格式如下</p>
<pre><code class="language-python"><div>    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">VtBarData</span><span class="hljs-params">(VtBaseData)</span>:</span>
    <span class="hljs-string">"""K线数据"""</span>

    <span class="hljs-comment">#----------------------------------------------------------------------</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self)</span>:</span>
        <span class="hljs-string">"""Constructor"""</span>
        super(VtBarData, self).__init__()
        
        self.vtSymbol = EMPTY_STRING        <span class="hljs-comment"># vt系统代码</span>
        self.symbol = EMPTY_STRING          <span class="hljs-comment"># 代码</span>
        self.exchange = EMPTY_STRING        <span class="hljs-comment"># 交易所</span>
    
        self.open = EMPTY_FLOAT             <span class="hljs-comment"># OHLC</span>
        self.high = EMPTY_FLOAT
        self.low = EMPTY_FLOAT
        self.close = EMPTY_FLOAT
        
        self.date = EMPTY_STRING            <span class="hljs-comment"># bar开始的时间，日期</span>
        self.time = EMPTY_STRING            <span class="hljs-comment"># 时间</span>
        self.datetime = <span class="hljs-keyword">None</span>                <span class="hljs-comment"># python的datetime时间对象</span>
        
        self.volume = EMPTY_INT             <span class="hljs-comment"># 成交量</span>
        self.openInterest = EMPTY_INT       <span class="hljs-comment"># 持仓量  </span>
        self.interval = EMPTY_UNICODE       <span class="hljs-comment"># K线周期</span>
</div></code></pre>
<p>onBar默认是一分钟推送一次，第一次推送在第一个整分钟。</p>
<pre><code class="language-python"><div>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">onBar</span><span class="hljs-params">(self, bar)</span>:</span>
        <span class="hljs-string">"""收到Bar推送（必须由用户继承实现）"""</span>
        <span class="hljs-keyword">raise</span> NotImplementedError
</div></code></pre>
<p>停止单，目前还没用过，等用过再来补充</p>
<pre><code class="language-python"><div>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">onStopOrder</span><span class="hljs-params">(self, so)</span>:</span>
        <span class="hljs-string">"""收到停止单推送（必须由用户继承实现）"""</span>
        <span class="hljs-keyword">raise</span> NotImplementedError
</div></code></pre>
<p>buy，sell，short，cover是四种下单方式，在onOrder里介绍了
这里要说明的是这四种下单方式的函数会返回一个list，list里只有一个元素，这个元素是vtOrderID</p>
<pre><code class="language-python"><div>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">buy</span><span class="hljs-params">(self, vtSymbol, price, volume, priceType = PRICETYPE_LIMITPRICE, 
    stop=False)</span>:</span>
        <span class="hljs-string">"""买开"""</span>
        <span class="hljs-keyword">return</span> self.sendOrder(CTAORDER_BUY, vtSymbol, price, volume, 
        priceType, stop)

        <span class="hljs-comment"># ----------------------------------------------------------------------</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sell</span><span class="hljs-params">(self, vtSymbol, price, volume, priceType = PRICETYPE_LIMITPRICE,
    stop=False)</span>:</span>
        <span class="hljs-string">"""卖平"""</span>
        <span class="hljs-keyword">return</span> self.sendOrder(CTAORDER_SELL, vtSymbol, price, volume, 
        priceType, stop)

        <span class="hljs-comment"># ----------------------------------------------------------------------</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">short</span><span class="hljs-params">(self, vtSymbol, price, volume, priceType = 
    PRICETYPE_LIMITPRICE, stop=False)</span>:</span>
        <span class="hljs-string">"""卖开"""</span>
        <span class="hljs-keyword">return</span> self.sendOrder(CTAORDER_SHORT, vtSymbol, price, volume, 
        priceType, stop)

        <span class="hljs-comment"># ----------------------------------------------------------------------</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">cover</span><span class="hljs-params">(self, vtSymbol, price, volume, priceType = 
    PRICETYPE_LIMITPRICE, stop=False)</span>:</span>
        <span class="hljs-string">"""买平"""</span>
        <span class="hljs-keyword">return</span> self.sendOrder(CTAORDER_COVER, vtSymbol, price, volume, 
        priceType, stop)
</div></code></pre>
<p>buy，sell，short，cover调用此函数发单</p>
<pre><code class="language-python"><div>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sendOrder</span><span class="hljs-params">(self, orderType, vtSymbol, price, volume, priceType = 
    PRICETYPE_LIMITPRICE, stop=False)</span>:</span>
        <span class="hljs-string">"""发送委托"""</span>
        <span class="hljs-keyword">if</span> self.trading:
            <span class="hljs-comment"># 如果stop为True，则意味着发本地停止单</span>
            <span class="hljs-keyword">if</span> stop:
                vtOrderIDList = self.ctaEngine.sendStopOrder(vtSymbol, orderType, price, volume, priceType, self)
            <span class="hljs-keyword">else</span>:
                vtOrderIDList = self.ctaEngine.sendOrder(vtSymbol, orderType, price, volume, priceType, self)
            <span class="hljs-keyword">return</span> vtOrderIDList
        <span class="hljs-keyword">else</span>:
            <span class="hljs-comment"># 交易停止时发单返回空字符串</span>
            <span class="hljs-keyword">return</span> []
</div></code></pre>
<p>cancelOrder取消订单，传入参数是vtOrderID，每次发单buy，sell，cover，short返回值都是一个列表
列表里只有一个元素就是vtOrderID，把那个vtOrderID传入cancelOrder函数，完成撤单</p>
<pre><code class="language-python"><div>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">cancelOrder</span><span class="hljs-params">(self, vtOrderID)</span>:</span>
        <span class="hljs-string">"""撤单"""</span>
        <span class="hljs-comment"># 如果发单号为空字符串，则不进行后续操作</span>
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> vtOrderID:
            <span class="hljs-keyword">return</span>

        <span class="hljs-keyword">if</span> STOPORDERPREFIX <span class="hljs-keyword">in</span> vtOrderID:
            self.ctaEngine.cancelStopOrder(vtOrderID)
        <span class="hljs-keyword">else</span>:
            self.ctaEngine.cancelOrder(vtOrderID)
</div></code></pre>
<p>cancelAll是循环vtOrderID去发撤单，所以为了程序的精细化处理一般不用cancelAll</p>
<pre><code class="language-python"><div>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">cancelAll</span><span class="hljs-params">(self)</span>:</span>
        <span class="hljs-string">"""全部撤单"""</span>
        self.ctaEngine.cancelAll(self.name)
</div></code></pre>
<p>如上，暂没有使用过StopOrder</p>
<pre><code class="language-python"><div>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">cancelAllStopOrder</span><span class="hljs-params">(self)</span>:</span>
        self.ctaEngine.cancelAllStopOrder(self.name)
</div></code></pre>
<p>batchCancelOrder批量撤单，如果单特别多，使用cancelOrder会慢，所以用batchCancelOrder</p>
<pre><code class="language-python"><div>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">batchCancelOrder</span><span class="hljs-params">(self,vtOrderIDList)</span>:</span>
        <span class="hljs-keyword">if</span> len(vtOrderIDList)&gt;<span class="hljs-number">5</span>:
            self.writeCtaLog(<span class="hljs-string">u'策略发送批量撤单委托失败，单量超过5张'</span>)
            <span class="hljs-keyword">return</span>
        self.ctaEngine.batchCancelOrder(vtOrderIDList)
</div></code></pre>
<p>回测中使用，但实盘没有tick可以load所以不loadtick</p>
<pre><code class="language-python"><div>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">loadTick</span><span class="hljs-params">(self, hours=<span class="hljs-number">1</span>)</span>:</span>
        <span class="hljs-string">"""读取tick数据"""</span>
        <span class="hljs-keyword">return</span> self.ctaEngine.loadTick(self.tickDbName, self.symbolList, 
        hours)
</div></code></pre>
<p>加载bar数据</p>
<pre><code class="language-python"><div>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">loadBar</span><span class="hljs-params">(self, hours=<span class="hljs-number">1</span>)</span>:</span>
        <span class="hljs-string">"""读取bar数据"""</span>
        <span class="hljs-keyword">return</span> self.ctaEngine.loadBar(self.barDbName, self.symbolList, hours)
</div></code></pre>
<p>非常重要的功能，会把日志打下来，方便复盘，但记住别放在交易逻辑之前，尽量放在之后</p>
<pre><code class="language-python"><div>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">writeCtaLog</span><span class="hljs-params">(self, content)</span>:</span>
        <span class="hljs-string">"""记录CTA日志"""</span>
        content = self.name + <span class="hljs-string">':'</span> + content
        self.ctaEngine.writeCtaLog(content)
</div></code></pre>
<p>loadHistoryBar可以在实盘中通过交易所提供的restful Api获取一定数量的bar，</p>
<pre><code class="language-python"><div>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">loadHistoryBar</span><span class="hljs-params">(self,vtSymbol,type_,size= None,since = None)</span>:</span>
        <span class="hljs-string">"""策略开始前下载历史数据"""</span>

        <span class="hljs-keyword">if</span> type_ <span class="hljs-keyword">in</span> [<span class="hljs-string">"1min"</span>,<span class="hljs-string">"5min"</span>,<span class="hljs-string">"15min"</span>,<span class="hljs-string">"30min"</span>,<span class="hljs-string">"60min"</span>,<span class="hljs-string">"120min"</span>,<span class="hljs-string">"240min"</span>,
        <span class="hljs-string">"360min"</span>,<span class="hljs-string">"480min"</span>,<span class="hljs-string">"1day"</span>,<span class="hljs-string">"1week"</span>,<span class="hljs-string">"1month"</span>]:
            data = self.ctaEngine.loadHistoryBar(vtSymbol,type_,size,since)
            lastbar = data[<span class="hljs-number">-1</span>]
            <span class="hljs-keyword">if</span> <span class="hljs-string">'min'</span> <span class="hljs-keyword">in</span> type_:
                minute = int(type_[:<span class="hljs-number">-3</span>])

            <span class="hljs-keyword">if</span> datetime.now() &lt; (lastbar.datetime + timedelta(seconds = 
            <span class="hljs-number">60</span>*minute)):
                self.writeCtaLog(<span class="hljs-string">u'加载历史数据抛弃最后一个非完整K线，频率%s，时
                间%s'</span>%(type_, lastbar.datetime))
                data = data[:<span class="hljs-number">-1</span>]
                
            <span class="hljs-keyword">return</span> data
            
        <span class="hljs-keyword">else</span>:
            self.writeCtaLog(
                <span class="hljs-string">u'下载历史数据参数错误，请参考以下参数["1min","5min","15min",
                "30min","60min","120min","240min","360min","480min","1day",
                "1week","1month"]，同时size建议不大于2000'</span>)
            <span class="hljs-keyword">return</span>
</div></code></pre>
<p>可以给自己发邮件，在实盘中启用</p>
<pre><code class="language-python"><div>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">mail</span><span class="hljs-params">(self,my_context)</span>:</span>
        <span class="hljs-string">"""邮件发送模块"""</span>
        <span class="hljs-keyword">if</span> self.ctaEngine.engineType == ENGINETYPE_BACKTESTING:
            <span class="hljs-keyword">pass</span>
        <span class="hljs-keyword">else</span>:
            msg = mail(my_context,self)
            self.writeCtaLog(<span class="hljs-string">'%s'</span>%msg)
</div></code></pre>
<p>注册一个函数onXmimBar写函数名字
xmin写分钟数，必须是整分钟，比如5，15 这种，可以参考行情软件上的k线时间
然后会自动生成两个变量通过setattr(key,value)
一个是BarGenerator对象的
一个是ArrayManager对象的
名字是</p>
<pre><code class="language-auto"><div># if xmin: 
    #         variable = &quot;bg%sDict&quot;%xmin
    #         variable2 = &quot;am%sDict&quot;%xmin
    #     else:
    #         variable = &quot;bgDict&quot;
    #         variable2 = &quot;amDict&quot;
</div></code></pre>
<pre><code class="language-python"><div>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">generateBarDict</span><span class="hljs-params">(self, onBar, xmin=<span class="hljs-number">0</span>, onXminBar=None, size = <span class="hljs-number">100</span>, 
    alignment=<span class="hljs-string">'sharp'</span>, marketClose = <span class="hljs-params">(<span class="hljs-number">23</span>,<span class="hljs-number">59</span>)</span>)</span>:</span>
        <span class="hljs-keyword">if</span> xmin: 
            variable = <span class="hljs-string">"bg%sDict"</span>%xmin
            variable2 = <span class="hljs-string">"am%sDict"</span>%xmin
        <span class="hljs-keyword">else</span>:
            variable = <span class="hljs-string">"bgDict"</span>
            variable2 = <span class="hljs-string">"amDict"</span>
        bgDict= {
            sym: BarGenerator(onBar,xmin,onXminBar, alignment=alignment, 
            marketClose=marketClose)
            <span class="hljs-keyword">for</span> sym <span class="hljs-keyword">in</span> self.symbolList }
        
        amDict = {
            sym: ArrayManager(size)
            <span class="hljs-keyword">for</span> sym <span class="hljs-keyword">in</span> self.symbolList }

        setattr(self, variable, bgDict)
        setattr(self, variable2, amDict)
</div></code></pre>
<p>秒级别的bar，类似分钟级别的参数，一般是给高频，而且秒级别的噪声很大，一般需要很长的研究过程</p>
<pre><code class="language-python"><div>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">generateHFBar</span><span class="hljs-params">(self,xSecond,size = <span class="hljs-number">60</span>)</span>:</span>
        self.hfDict = {sym: BarGenerator(self.onHFBar,xSecond = xSecond)
                        <span class="hljs-keyword">for</span> sym <span class="hljs-keyword">in</span> self.symbolList}
        self.amhfDict = {sym: ArrayManager(size) <span class="hljs-keyword">for</span> sym <span class="hljs-keyword">in</span> self.symbolList}

</div></code></pre>

    </body>
    </html>